﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using Lidgren.Network;


namespace Networking
{
    public enum Headers
    {
        PlayerData,
        Text
    }

    public class Server
    {
        public int Port { get; set; }
        public delegate void ReceiveDataEventHandler(Headers header, NetIncomingMessage incmsg);
        public delegate void ClientDisconnect();
        public delegate void ClientConnect(NetConnection con);
        public event ReceiveDataEventHandler OnReceiveData;
        public event ClientDisconnect OnClientDisconnect;
        public event ClientConnect OnClientConnect;
        private NetServer NetServer;
        private NetPeerConfiguration Config;
        private List<Person> People;

        public Server(int port) // Initialize
        {
            this.Port = port;
            Config = new NetPeerConfiguration("AwesomeChat");
            Config.Port = port;
            NetServer = new NetServer(Config);
            NetServer.RegisterReceivedCallback(new SendOrPostCallback(ReceiveData));
        }

        public void Start()
        {
            NetServer.Start();
        }

        public void Stop()
        {
            People = null;
            NetServer.Shutdown("You're not welcome here.");
        }

        public void SendData(Headers header, object obj, NetConnection con)
        {
            NetOutgoingMessage outmsg = NetServer.CreateMessage();
            outmsg.Write((byte)header);
            outmsg.WriteAllProperties(obj);
            NetServer.SendMessage(outmsg, con, NetDeliveryMethod.ReliableSequenced);
        }

        public void SendData(Headers header, object obj, int fromid, NetConnection con)
        {
            NetOutgoingMessage outmsg = NetServer.CreateMessage();
            outmsg.Write((byte)header);
            outmsg.Write(fromid);
            outmsg.WriteAllProperties(obj);
            NetServer.SendMessage(outmsg, con, NetDeliveryMethod.ReliableSequenced);
        }

        private void ReceiveData(object callback)
        {
            NetIncomingMessage incmsg;
            if ((incmsg = NetServer.ReadMessage()) != null)
            {
                switch(incmsg.MessageType)
                {
                    case NetIncomingMessageType.StatusChanged:

                        NetConnectionStatus status = (NetConnectionStatus)incmsg.ReadByte();

                        if (status == NetConnectionStatus.Connected)
                            if (OnClientConnect != null) OnClientConnect(incmsg.SenderConnection);
                        if (status == NetConnectionStatus.Disconnected)
                            if (OnClientDisconnect != null) OnClientDisconnect();

                        break;

                    case NetIncomingMessageType.Data:

                        Headers header = (Headers)incmsg.ReadByte();
                        if (OnReceiveData != null) OnReceiveData(header, incmsg);
                        break;
                }
            }
        }
    }

    public class Person
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public NetConnection Connection;

        public Person() { }
    }
}
